package io.wins.vertx.verticle.api;

import io.vertx.core.Future;
import io.vertx.core.eventbus.Message;
import io.vertx.core.json.JsonArray;
import io.vertx.core.json.JsonObject;
import io.vertx.core.logging.Logger;
import io.vertx.core.logging.LoggerFactory;
import io.wins.vertx.database.JdbcExecutor;
import io.wins.vertx.entity.Concert;
import io.wins.vertx.entity.Tag;
import io.wins.vertx.service.BaseService;
import io.wins.vertx.service.ConcertService;
import org.apache.commons.lang3.StringUtils;

public class ConcertApiVerticle extends RestApiVerticle {

    public static final String CONCERT_REST_ADDRESS = "io.wins.rest.concert#%1$s";
    public static final String CREATE_CONCERT = "createConcert";
    public static final String UPDATE_CONCERT = "updateConcert";
    public static final String DELETE_CONCERT = "deleteConcert";
    public static final String LIST_CONCERT = "listConcert";
    public static final String LOAD_CONCERT = "loadConcert";
    public static final String PUBLISH_CONCERT = "publishConcert";
    public static final String CREATE_TAG = "createTag";
    public static final String LIST_TAGS = "listTags";
    public static final String CONCERT_TIME = "concertTime";
    public static final String FACE_VALUES = "faceValues";
    private static final Logger logger = LoggerFactory.getLogger(ConcertApiVerticle.class);

    public final ConcertService service;

    public ConcertApiVerticle(final ConcertService service) {
        this.service = service;
    }

    @Override
    public void start(final Future<Void> startFuture) throws Exception {
        super.start();
        this.on(String.format(CONCERT_REST_ADDRESS, CREATE_CONCERT), this::createConcert);
        this.on(String.format(CONCERT_REST_ADDRESS, UPDATE_CONCERT), this::updateConcert);
        this.on(String.format(CONCERT_REST_ADDRESS, DELETE_CONCERT), this::deleteConcert);
        this.on(String.format(CONCERT_REST_ADDRESS, LIST_CONCERT), this::listConcert);
        this.on(String.format(CONCERT_REST_ADDRESS, LOAD_CONCERT), this::loadConcert);
        this.on(String.format(CONCERT_REST_ADDRESS, PUBLISH_CONCERT), this::publish);
        this.on(String.format(CONCERT_REST_ADDRESS, CREATE_TAG), this::createTag);
        this.on(String.format(CONCERT_REST_ADDRESS, LIST_TAGS), this::listTags);
        this.on(String.format(CONCERT_REST_ADDRESS, CONCERT_TIME), this::concertTime);
        this.on(String.format(CONCERT_REST_ADDRESS, FACE_VALUES), this::faceValues);
        startFuture.complete();
    }

    private void concertTime(final Message<JsonObject> tMessage) {
        final JsonObject param = tMessage.body().getJsonObject("param");
        final String pid = param.getString("pid");
        this.service.getConcertTime(pid, tMessage);
    }

    private void faceValues(final Message<JsonObject> tMessage) {
        final JsonObject param = tMessage.body().getJsonObject("param");
        final String pid = param.getString("pid");
        this.service.getFaceValues(pid, tMessage);
    }

    private void updateConcert(final Message<JsonObject> tMessage) {
        final JsonObject body = tMessage.body().getJsonObject("body").getJsonObject("concert");
        final Concert concert = new Concert(body);
        this.service.updateConcert(concert, tMessage);
    }

    private void loadConcert(final Message<JsonObject> tMessage) {
        final JsonObject param = tMessage.body().getJsonObject("param");
        final String id = param.getString("id");
        this.service.getConcertById(id, tMessage);
    }

    private void listConcert(final Message<JsonObject> tMessage) {
        final JsonObject param = tMessage.body().getJsonObject("param");
        final String init = param.getString("init");
        final String type = param.getString("type");
        final int page = Integer.valueOf(param.getString("page"));
        final int limit = Integer.valueOf(param.getString("limit"));
        if (StringUtils.isEmpty(type)) {
            this.listConcertByPage(init, page, limit, tMessage);
        } else {
            this.listTypeConcertByPage(type, init, page, limit, tMessage);
        }
    }

    private void listTypeConcertByPage(final String type, final String init, final int page, final int limit, final Message<JsonObject> tMessage) {
        if ("1".equals(init)) {
            this.vertx.eventBus().send(JdbcExecutor.CONSUMER, new JsonObject().put("action", "select")
                .put(BaseService.SQL, "select count(*) as total from ds_concert where is_delete = '0' and type = ?")
                .put(BaseService.PARAMS, new JsonArray().add(type)), r -> {
                if (r.succeeded()) {
                    tMessage.body().put("total", ((JsonArray) r.result().body()).getJsonObject(0).getValue("total"));
                    this.service.listTypeConcertByPage(type, page, limit, tMessage);
                } else {
                    tMessage.fail(404, "no type of concert");
                }
            });
        } else {
            this.service.listTypeConcertByPage(type, page, limit, tMessage);
        }
    }

    private void listConcertByPage(final String init, final int page, final int limit, final Message<JsonObject> tMessage) {
        if ("1".equals(init)) {
            this.vertx.eventBus().send(JdbcExecutor.CONSUMER, new JsonObject().put("action", "select")
                .put("sql", "select count(*) as total from ds_concert where is_delete = '0'"), r -> {
                if (r.succeeded()) {
                    tMessage.body().put("total", ((JsonArray) r.result().body()).getJsonObject(0).getValue("total"));
                    this.service.listConcertByPage(page, limit, tMessage);
                } else {
                    this.service.listAllConcert(tMessage);
                }
            });
        } else {
            this.service.listConcertByPage(page, limit, tMessage);
        }
    }

    private void deleteConcert(final Message<JsonObject> tMessage) {
        final JsonObject param = tMessage.body().getJsonObject("param");
        final String id = param.getString("id");
        this.service.deleteConcert(id, tMessage);
    }

    private void createConcert(final Message<JsonObject> tMessage) {
        final JsonObject body = tMessage.body().getJsonObject("body").getJsonObject("concert");
        final Concert concert = new Concert(body);
        this.service.insertConcert(concert, tMessage);
    }

    private void publish(final Message<JsonObject> tMessage) {
        final String id = tMessage.body().getJsonObject("param").getString("id");
        final String status = tMessage.body().getJsonObject("body").getString("status");
        this.service.publish(id, status, tMessage);
    }

    private void createTag(final Message<JsonObject> tMessage) {
        final JsonObject body = tMessage.body().getJsonObject("body").getJsonObject("tag");
        final Tag tag = new Tag(body);
        this.service.createTag(tag, tMessage);
    }

    private void listTags(final Message<JsonObject> tMessage) {
        final JsonArray codes = tMessage.body().getJsonObject("body").getJsonArray("codes");
        if (codes == null) {
            this.service.listTags(tMessage);
        } else {
            this.service.listTags(codes, tMessage);
        }
    }

}
